package kmeans.esecuzione;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import kmeans.classificazione.Classificatore;
import kmeans.classificazione.ValutazioneClassificatore;
import kmeans.documenti.Documento;
import kmeans.documenti.LettoreFile;
import edu.udo.cs.wvtool.config.WVTConfiguration;
import edu.udo.cs.wvtool.config.WVTConfigurationFact;
import edu.udo.cs.wvtool.generic.vectorcreation.TFIDF;
import edu.udo.cs.wvtool.main.WVTDocumentInfo;
import edu.udo.cs.wvtool.main.WVTFileInputList;
import edu.udo.cs.wvtool.main.WVTWordVector;
import edu.udo.cs.wvtool.main.WVTool;
import edu.udo.cs.wvtool.util.WVToolException;
import edu.udo.cs.wvtool.wordlist.WVTWordList;


public class EsecuzioneClassificazione {
	private LettoreFile training;
	private LettoreFile test;
	private LettoreFile risultati;
	private WVTool wvt;
	/**
	 * @param args
	 * @throws IOException 
	 */
	
	public EsecuzioneClassificazione(){}
	
	/*inizializza la libreria wvtool e l'insieme delle wordList 
	 * con le quali è possibile vettorializzare i documenti*/
	public WVTWordList initWordList(String path) throws IOException, WVToolException{
		wvt = new WVTool(true);
		// Initialize the configuration
		WVTConfiguration config = new WVTConfiguration();
        config.setConfigurationRule(WVTConfiguration.STEP_VECTOR_CREATION, new WVTConfigurationFact(new TFIDF()));
		System.out.println("inizializzata la wordlist");
		WVTDocumentInfo doc_path = new WVTDocumentInfo(path, "txt", "", "english", 0);
		// Initialize the input list with two classes
	    WVTFileInputList list = new WVTFileInputList(1);
	    // Add entries
	    list.addEntry(doc_path);
        WVTWordList wordList = wvt.createWordList(list, config);
        this.setWVT(wvt);
        return wordList;
	}
	
	/*per ogni Documento crea il vettore pesato tf-idf in base alle parole nella wordList*/
	public void initVector(WVTool wvt, WVTWordList wordlist, LettoreFile file) throws WVToolException{
		WVTWordVector wordVector;
		Documento d;
		int i;
		for(i = 0; i<file.getDocs().size(); i++){
			d = file.getDocs().get(i);
			wordVector = wvt.createVector(d.getContenuto(),wordlist);
			d.setVector(wordVector.getValues());			
		}		
	}
	  
	public static void main(String[] args) throws IOException, WVToolException {
		EsecuzioneClassificazione esecuzione= new EsecuzioneClassificazione();
		/*leggo i documenti di test e di training*/
		esecuzione.setTraining(new LettoreFile("training.txt", "../tesinaIA/training/"));
		esecuzione.setTest(new LettoreFile("test.txt", "../tesinaIA/test/"));
		esecuzione.setRisultati(new LettoreFile("", "../tesinaIA/risultati/"));
		LettoreFile test = esecuzione.getTest();
		LettoreFile training = esecuzione.getTraining();
		LettoreFile risultati = esecuzione.getRisultati();
		esecuzione.getTest().Lettore();
		esecuzione.getTraining().Lettore();
		/*inizializzo la wordlist*/
		WVTWordList wordlist = esecuzione.initWordList("../tesinaIA/training");
		/*calcolo i vettori tf-idf per ogni documento*/
		esecuzione.initVector(esecuzione.getWVT(), wordlist, training);
		esecuzione.initVector(esecuzione.getWVT(), wordlist, test);
		
		int categorie = esecuzione.getTraining().getCat_docs().keySet().size();
		/*addestro il classificatore sull'insieme di training*/
		/*classifico l'insieme di training in K gruppi*/
		Classificatore class_training = new Classificatore(categorie,training.getDocs(),training.getCat_docs());
		List<Double[]> centri = class_training.initCentri(training.getDocs(), categorie, 0.5);
		Map<Integer, List<Documento>> map_training = class_training.algoritmo_K_Means(training.getDocs(), centri, categorie);
		int[][] m = class_training.risultatiClassificatore(map_training, training.getCat_docs().keySet());
		String[] classi = class_training.getClassi();
		/*associo ogni gruppo ottenuto dal classificatore alla predizione di una categoria*/
		Map<String, List<Integer>> cat_assegnate = class_training.assegnaCategorie(m, classi);
		risultati.writeToFile("classificatoreTRAINING", class_training.getStampa());
		
		/*valuto il classificatore sull'insieme di test*/
		/*classifico l'insieme di test in K gruppi*/
		Classificatore class_test = new Classificatore(categorie,test.getDocs(),test.getCat_docs());
		Map<Integer, List<Documento>> map_test = class_test.algoritmo_K_Means(test.getDocs(), centri, categorie);
		class_test.risultatiClassificatore(map_test, training.getCat_docs().keySet());
		risultati.writeToFile("classificatoreTEST", class_test.getStampa());
		/*valuto la classificazione ottenuta*/
		ValutazioneClassificatore v = new ValutazioneClassificatore();
		/* genero la matrice di contingenza e calcolo: accuratezza, error rate e 
		 * per ogni categoria la precision e la recall
		 */
		v.valutazioneClassificatore(cat_assegnate, map_test, classi);
		risultati.writeToFile("valutazione_classificatore", v.getStampa());
		/*elimino i file generati dalla lettura dei documenti di test e di training*/
		training.removeFile("../tesinaIA/training/");
		test.removeFile("../tesinaIA/test/");
	}
	
	public LettoreFile getTest() {
		return test;
	}
	public LettoreFile setTest(LettoreFile test) {
		this.test = test;
		return test;
	}
	public LettoreFile getTraining() {
		return training;
	}
	public LettoreFile setTraining(LettoreFile training) {
		this.training = training;
		return training;
	}
	public LettoreFile getRisultati() {
		return risultati;
	}
	public void setRisultati(LettoreFile risultati) {
		this.risultati = risultati;
	}
	private WVTool getWVT() {
		return this.wvt;	
	}
	
	private void setWVT(WVTool wvt) {
		this.wvt = wvt;	
	}
}
